/*
*
* ████████╗░█████╗░███████╗██████╗░░█████╗░
* ╚══██╔══╝██╔══██╗██╔════╝██╔══██╗██╔══██╗
* ░░░██║░░░██║░░██║█████╗░░██████╦╝███████║
* ░░░██║░░░██║░░██║██╔══╝░░██╔══██╗██╔══██║
* ░░░██║░░░╚█████╔╝██║░░░░░██████╦╝██║░░██║
* ░░░╚═╝░░░░╚════╝░╚═╝░░░░░╚═════╝░╚═╝░░╚═╝
* 
*  :: 九方通逊-Henry ::   Copyright©2020 tofba.com  
* 
*/
package com.lmexpress.service.impl;

import java.io.File;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lmexpress.enums.ApiCredential;
import com.lmexpress.enums.ApiOrderError;
import com.lmexpress.enums.LabelFormat;
import com.lmexpress.enums.LabelSuffix;
import com.lmexpress.orm.hualei.HLOrder;
import com.lmexpress.orm.hualei.OrderInvoiceParam;
import com.lmexpress.orm.hualei.OrderVolumeParam;
import com.lmexpress.orm.openapi.ExpressOrderApi;
import com.lmexpress.orm.openapi.OrderInvoice;
import com.lmexpress.orm.openapi.OrderVolume;
import com.lmexpress.orm.rest.ApiLabelResponse;
import com.lmexpress.orm.rest.ApiOrderResponse;
import com.lmexpress.service.ApiService;
import com.lmexpress.util.ApiUtil;
import com.lmexpress.util.HttpClientPoolUtil;
import com.lmexpress.util.HttpClientResult;

/**
 * <华磊小包系统>
 * 
 * @author Henry(fba02)
 * @version [版本号, 2020-12-09]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class HuaLeiClient implements ApiService {
	private Logger LOGGER = LoggerFactory.getLogger(HuaLeiClient.class);
	private final static String ACK = "true";
	private final static String CUSTOMER_ID = "customer_id";
	private final static String CUSTOMER_USERID = "customer_userid";
	private final static String DEFAULT_TRADE_TYPE = "ZYXT";

	@Override
	public ApiOrderResponse preProcessCreateOrder(ExpressOrderApi expressOrderApi) {
		return null;
	}

	@Override
	public String mapping(ExpressOrderApi expressOrderApi) {
		HLOrder hlOrder = new HLOrder();
		hlOrder.setOrder_returnsign(expressOrderApi.getReturnSign());
		hlOrder.setOrder_customerinvoicecode(expressOrderApi.getCustomerInvoiceCode());
		hlOrder.setTrade_type(DEFAULT_TRADE_TYPE);
		hlOrder.setCountry(expressOrderApi.getCountryCode());
		Map<String, Integer> authMap = selectAuth(expressOrderApi.getApiCredentials());
		if (null != authMap) {
			hlOrder.setCustomer_id(authMap.get(CUSTOMER_ID));
			hlOrder.setCustomer_userid(authMap.get(CUSTOMER_USERID));
		}
		Map<String, String> apiCredentials = expressOrderApi.getApiCredentials();
		apiCredentials.get(ApiCredential.HUALEI_PRODUCT_CODE.getKey());
		hlOrder.setProduct_id(String.valueOf(expressOrderApi.getProductId()));
		hlOrder.setTracking_number(expressOrderApi.getTrackingNumber());

		hlOrder.setOrder_piece(expressOrderApi.getOrderPiece());
		hlOrder.setOrder_transactionurl(expressOrderApi.getTransactionUrl());

		hlOrder.setConsignee_name(expressOrderApi.getConsigneeName());
		hlOrder.setConsignee_address(expressOrderApi.getConsigneeAddress());
		hlOrder.setConsignee_city(expressOrderApi.getConsigneeCity());
		String consigneeMobile = expressOrderApi.getConsigneeMobile();
		if (StringUtils.isNotBlank(consigneeMobile)) {
			consigneeMobile.replaceAll("[a-zA-Z.]", "");
		}
		hlOrder.setConsignee_mobile(consigneeMobile);
		String zipCode = expressOrderApi.getConsigneePostCode();
		String countryCode = expressOrderApi.getCountryCode();
		if (Objects.equals(expressOrderApi.getProductId(), 2381L)) {
			if (StringUtils.isNotBlank(zipCode) && zipCode.length() > 5 && zipCode.indexOf("-") > -1) {
				zipCode = zipCode.substring(0, zipCode.indexOf("-"));
			}
		}
		hlOrder.setOrder_insurance(expressOrderApi.getInsuranceAmount() == null ? 0.1 : expressOrderApi.getInsuranceAmount());
		hlOrder.setCountry(countryCode);
		hlOrder.setConsignee_postcode(zipCode);
		hlOrder.setConsignee_state(expressOrderApi.getConsigneeState());
		hlOrder.setConsignee_telephone(expressOrderApi.getConsigneeTelephone());
		hlOrder.setConsignee_email(expressOrderApi.getConsigneeEmail());
		hlOrder.setConsignee_companyname(expressOrderApi.getConsigneeCompanyName());
		hlOrder.setShipper_name(expressOrderApi.getShipperName());
		hlOrder.setShipper_companyname(expressOrderApi.getShipperCompanyName());
		hlOrder.setShipper_address1(expressOrderApi.getShipperAddress1());
		hlOrder.setShipper_address2(expressOrderApi.getShipperAddress2());
		hlOrder.setShipper_address3(expressOrderApi.getShipperAddress3());
		hlOrder.setShipper_city(expressOrderApi.getShipperCity());
		hlOrder.setShipper_state(expressOrderApi.getShipperState());
		hlOrder.setShipper_postcode(expressOrderApi.getShipperPostCode());
		hlOrder.setShipper_country(expressOrderApi.getShipperCountry());
		hlOrder.setShipper_telephone(expressOrderApi.getShipperTelephone());
		List<OrderInvoice> orderInvoices = expressOrderApi.getOrderInvoices();
		List<OrderInvoiceParam> orderInvoiceParams = new ArrayList<OrderInvoiceParam>();
		Double totalWeight = 0D;
		for (OrderInvoice orderInvoice : orderInvoices) {
			OrderInvoiceParam orderInvoiceParam = new OrderInvoiceParam();
			orderInvoiceParam.setHs_code(orderInvoice.getHsCode());
			orderInvoiceParam.setInvoice_amount(String.valueOf(orderInvoice.getInvoiceAmount()));
			orderInvoiceParam.setInvoice_pcs(String.valueOf(orderInvoice.getInvoicePcs()));
			String skuen = orderInvoice.getSkuNameEn();
			orderInvoiceParam.setInvoice_title(skuen);
			orderInvoiceParam.setSku(orderInvoice.getSkuNameCn());
			orderInvoiceParam.setSku_code(orderInvoice.getSkuCode());
			orderInvoiceParam.setInvoice_purpose(orderInvoice.getInvoicePurpose());
			if (null != orderInvoice.getInvoiceWeight()) {
				orderInvoiceParam.setInvoice_weight(String.valueOf(orderInvoice.getInvoiceWeight()));
				totalWeight += orderInvoice.getInvoiceWeight();
			}
			orderInvoiceParam.setInvoice_currency(expressOrderApi.getCurrencyCode());
			orderInvoiceParams.add(orderInvoiceParam);
		}
		if (null == hlOrder.getWeight() && totalWeight > 0D) {
			hlOrder.setWeight(totalWeight);
		}
		totalWeight = 0D;
		hlOrder.setOrderInvoiceParam(orderInvoiceParams);
		List<OrderVolume> orderVolumes = expressOrderApi.getOrderVolumes();
		List<OrderVolumeParam> orderVolumeParams = new ArrayList<OrderVolumeParam>();
		if (CollectionUtils.isNotEmpty(orderVolumes)) {
			for (OrderVolume orderVolume : orderVolumes) {
				OrderVolumeParam orderVolumeParam = new OrderVolumeParam();
				Double length = orderVolume.getLength();
				Double width = orderVolume.getWidth();
				Double height = orderVolume.getHeight();
				Double weight = orderVolume.getWeight();
				if (null != length) {
					orderVolumeParam.setVolume_length(String.valueOf(length));
				}
				if (null != width) {
					orderVolumeParam.setVolume_width(String.valueOf(width));
				}
				if (null != height) {
					orderVolumeParam.setVolume_height(String.valueOf(height));
				}
				if (null != weight) {
					orderVolumeParam.setVolume_weight(String.valueOf(weight));
					totalWeight += weight;
				}
				orderVolumeParams.add(orderVolumeParam);
			}
			hlOrder.setOrderVolumeParam(orderVolumeParams);
		}
		if (null == hlOrder.getWeight() && totalWeight > 0D) {
			hlOrder.setWeight(totalWeight);
		}
		return new Gson().toJson(hlOrder);
	}

	/**
	 * <认证>
	 * 
	 * @return
	 * @author Henry(fba02)
	 * @version [版本号, 2020-10-20]
	 * @see [类、类#方法、类#成员]
	 */
	public Map<String, Integer> selectAuth(Map<String, String> apiCredentials) {
		String auth = apiCredentials.get(ApiCredential.HUALEI_SERVER_URL.getKey()) + "selectAuth.htm?username=" + apiCredentials.get(ApiCredential.HUALEI_USERNAME.getKey()) + "&password=" + apiCredentials.get(ApiCredential.HUALEI_PASSWORD.getKey());
		try {
			HttpClientResult httpClientResult = HttpClientPoolUtil.doGet(auth);
			if (null == httpClientResult) {
				return null;
			}
			String content = httpClientResult.getContent();
			if (StringUtils.isBlank(content)) {
				return null;
			}
			Map<String, String> responseMap = new Gson().fromJson(URLDecoder.decode(content, "utf-8"), new TypeToken<Map<String, String>>() {
			}.getType());
			if (ACK.equalsIgnoreCase(responseMap.get("ack"))) {
				Map<String, Integer> result = new HashMap<String, Integer>();
				result.put("customer_id", Integer.valueOf(responseMap.get(CUSTOMER_ID)));
				result.put("customer_userid", Integer.valueOf(responseMap.get(CUSTOMER_USERID)));
				return result;
			}
			return null;
		} catch (Exception e) {
			LOGGER.error("hl.auth.exception:", e);
			return null;
		}
	}

	@Override
	public ApiOrderResponse createOrder(ExpressOrderApi expressOrderApi) {
		try {
			Map<String, String> pipeline = expressOrderApi.getApiCredentials();
			String orderJson = mapping(expressOrderApi);
			orderJson = StringEscapeUtils.unescapeJava(orderJson).replaceAll("&", "").replaceAll("#", "");
			orderJson = URLEncoder.encode(orderJson, "UTF-8");
			LOGGER.info("hl.shipment.request:{}", orderJson);
			HttpClientResult httpClientResult = HttpClientPoolUtil.doPost(pipeline.get(ApiCredential.HUALEI_SERVER_URL.getValue()) + "param=" + orderJson);
			if (null == httpClientResult || httpClientResult != null && StringUtils.isBlank(httpClientResult.getContent())) {
				return new ApiOrderResponse(false, null, ApiOrderError.SERVICE_NO_DATA_RETURN.getMessage(), true, null);
			}
			String responseJson = httpClientResult.getContent();
			Map<String, Object> responseMap = new Gson().fromJson(responseJson, new TypeToken<Map<String, Object>>() {
			}.getType());
			String message = (String) responseMap.get("message");
			String ack = (String) responseMap.get("ack");
			if (StringUtils.isNotBlank(message)) {
				message = URLDecoder.decode(message, "utf-8");
			}
			if (ACK.equalsIgnoreCase(ack)) {
				// 第三方订单号
				String thirdPartyorderNo = (String) responseMap.get("order_id");
				// 参考号
				String referenceNo = (String) responseMap.get("reference_number");
				// 追踪号
				String trackNumber = (String) responseMap.get("tracking_number");
				ApiLabelResponse apiLabelResponse = label(thirdPartyorderNo, trackNumber, pipeline);
				ApiOrderResponse apiOrderResponse = new ApiOrderResponse();
				apiOrderResponse.setSuccess(true);
				apiOrderResponse.setTrackNumber(trackNumber);
				apiOrderResponse.setThirdPartyorderNo(thirdPartyorderNo);
				apiOrderResponse.setReferenceNo(referenceNo);
				apiOrderResponse.setOriginalResponse(responseJson);
				if (StringUtils.isNotBlank(apiLabelResponse.getLabelPath())) {
					// 远程面单路径
					apiOrderResponse.setLabelUrl(apiLabelResponse.getLabelPath());
				}
				if (StringUtils.isNotBlank(apiLabelResponse.getRelativePath())) {
					// 本地服务器路径
					apiOrderResponse.setLmLabelUrl(apiLabelResponse.getRelativePath());
				}
				return apiOrderResponse;
			}
			return new ApiOrderResponse(false, null, message, false, null);
		} catch (Exception e) {
			LOGGER.error("hl.shipment.exception", e);
			return new ApiOrderResponse(false, null, ApiOrderError.CREATE_ORDER_EXCEPTION.getMessage(), false, null);
		}
	}

	@Override
	public ApiLabelResponse label(String trackNumber, Map<String, String> configureMap) {
		return null;
	}

	@Override
	public ApiLabelResponse label(String referenceNo, String trackNumber, Map<String, String> configureMap) {
		try {
			String serverUrl = configureMap.get(ApiCredential.HUALEI_LABEL_URL.getKey());
			String format = configureMap.get(ApiCredential.HUALEI_LABELFORMAT.getKey());
			String url = serverUrl + "?Format=" + format + "&PrintType=1&order_id=" + referenceNo;
			String pdfName = trackNumber + LabelSuffix.PDF.getSuffix();
			String centrePath = ApiUtil.getCurrentDay() + File.separator;
			String relativePath = DEFAULT_LABEL_FOLDER + File.separator + centrePath;
			String folderPath = DEFAULT_LABEL_ROOT + relativePath;
			if (!new File(folderPath).exists()) {
				new File(folderPath).mkdirs();
			}
			String fileUrl = folderPath + pdfName;
			ApiLabelResponse apiLabelResponse = new ApiLabelResponse();
			try {
				FileUtils.copyURLToFile(new URL(url), new File(fileUrl));
				apiLabelResponse.setRelativePath(relativePath + pdfName);
			} catch (Exception e) {
				LOGGER.error("hl.copy.url.to.file.exception:{}", e);
			}
			apiLabelResponse.setBarCode(trackNumber);
			apiLabelResponse.setLabelPath(url);
			apiLabelResponse.setLabelFormat(LabelFormat.PDF.getFormat());
			return apiLabelResponse;
		} catch (Exception e) {
			LOGGER.error("hl.label.exception:{}", e.getMessage());
			return new ApiLabelResponse(trackNumber, null);
		}
	}

	@Override
	public ApiLabelResponse labelRender(String trackNumber, ExpressOrderApi expressOrderApi) {
		return null;
	}

	@Override
	public void tracking(String trackNumber, Map<String, String> configureMap) {

	}

	@Override
	public String trackNumber(String code, Map<String, String> configureMap) {
		return null;
	}

	public static void main(String[] args) {
		String server = "http://jfxb.tofba.com:8082/";
		String username = "J1884";
		String key = server + "_" + username + "_" + "customer_id";
		Cache<String, Integer> cache = Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).maximumSize(100).build();
		for (int i = 0; i < 10; i++) {
			try {
				System.out.println(ApiUtil.getCurrentDateTime() + ",get cache." + cache.getIfPresent(key));

				HttpClientResult httpClientResult = HttpClientPoolUtil.doGet(server + "selectAuth.htm?username=" + username + "&password=123456");
				if (null == httpClientResult) {
					return;
				}
				String content = httpClientResult.getContent();
				if (StringUtils.isBlank(content)) {
					return;
				}
				Map<String, String> responseMap = new Gson().fromJson(URLDecoder.decode(content, "utf-8"), new TypeToken<Map<String, String>>() {
				}.getType());
				if (ACK.equalsIgnoreCase(responseMap.get("ack"))) {
					Integer customer_id = Integer.valueOf(responseMap.get("customer_id"));
					Integer customer_userid = Integer.valueOf(responseMap.get("customer_userid"));
					System.out.println(customer_id + "," + customer_userid);
					cache.put(server + "_" + username + "_" + "customer_id", customer_id);
					cache.put(server + "_" + username + "_" + "customer_userid", customer_userid);
					System.out.println(cache.getIfPresent(key));
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}